package com.axapoint.opoc.core.dao;

import java.util.Collection;
import java.util.LinkedList;

import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;

import org.hibernate.annotations.Cascade;
import org.joda.time.DateTime;
import org.joda.time.Interval;

import com.anasoft.os.daofusion.bitemporal.WrappedBitemporalProperty;
import com.anasoft.os.daofusion.bitemporal.WrappedValueAccessor;

@Entity
@Table(name = "Engagement")
public class Engagement extends ObjectRegistration<Engagement, Engagement.Value, Engagement.Bitemporal> {
	private static final long serialVersionUID = 9168710745762860711L;

	@Entity
	@Table(name = "EngagementValues")
	public static final class Value extends _Value<Engagement, Bitemporal> {
		private static final long serialVersionUID = 1L;

		Value(Engagement unit, String systemId, String userId, Operation operation, String comment, Value value) {
			super(unit, systemId, userId, operation, comment);
		}
		public Value() {
		}
		@Override
		public String diff(_Value<Engagement, Bitemporal> otherValue, DateTime t0, DateTime t1) {
			StringBuffer sb = new StringBuffer();
			Value other = (Value)otherValue;
//XXX:		
			return sb.toString();
		}
		@Override
		public String toString() {
			StringBuffer sb = new StringBuffer();
			sb.append(super.toString());

			int cnt = 0;
			for (CprInterval.Value v : getEntity().getCprIntervals()) {
				if (v.getBitemporal().getValidityInterval().contains(getBitemporal().getValidityInterval().getStart())) {
					cnt++;
				}
			}
			sb.append("  #cprIntervales=").append(cnt).append('\n');			

			cnt = 0;
			for (Leave.Value v : getEntity().getLeaves()) {
				if (v.getBitemporal().getValidityInterval().contains(getBitemporal().getValidityInterval().getStart())) {
					cnt++;
				}
			}
			sb.append("  #leaves=").append(cnt).append('\n');

			cnt = 0;
			for (PersonalChannel.Value v : getEntity().getPersonalChannels()) {
				if (v.getBitemporal().getValidityInterval().contains(getBitemporal().getValidityInterval().getStart())) {
					cnt++;
				}
			}
			sb.append("  #personalChannels=").append(cnt).append('\n');

			return sb.toString();
		}
	}
	
	@Entity
	@Table(name = "EngagementBitemporal")
	public static final class Bitemporal extends _Bitemporal<Bitemporal, Value> {
		private static final long serialVersionUID = -2132187534862370208L;
		
		protected Bitemporal() {}
	    private Bitemporal(Engagement.Value value, Interval validityInterval) {
	        super(value, validityInterval);
	    }
	    
	    @Override
	    public Bitemporal copyWith(Interval validityInterval) {
	    	return new Bitemporal(value, validityInterval);
	    }
	}

	@SuppressWarnings("deprecation")
	@OneToOne(fetch = FetchType.LAZY)
    @Cascade(value = { org.hibernate.annotations.CascadeType.ALL, org.hibernate.annotations.CascadeType.DELETE_ORPHAN })
    @JoinColumn(name="organizationId")
    private Organization.Value organization;	

	@SuppressWarnings("deprecation")
	@OneToMany(fetch = FetchType.LAZY)
    @Cascade(value = { org.hibernate.annotations.CascadeType.ALL, org.hibernate.annotations.CascadeType.DELETE_ORPHAN })
    @JoinColumn(name="leaveId")
    private Collection<Leave.Value> leaves = new LinkedList<Leave.Value>();	

	@SuppressWarnings("deprecation")
	@OneToMany(fetch = FetchType.LAZY)
    @Cascade(value = { org.hibernate.annotations.CascadeType.ALL, org.hibernate.annotations.CascadeType.DELETE_ORPHAN })
    @JoinColumn(name="intervalId")
    private Collection<CprInterval.Value> cprIntervals = new LinkedList<CprInterval.Value>();	

	@SuppressWarnings("deprecation")
	@OneToMany(fetch = FetchType.LAZY)
    @Cascade(value = { org.hibernate.annotations.CascadeType.ALL, org.hibernate.annotations.CascadeType.DELETE_ORPHAN })
    @JoinColumn(name="personalChannelId")
    private Collection<PersonalChannel.Value> personalChannels = new LinkedList<PersonalChannel.Value>();	

	public Engagement() {
		super();
	}
	public Collection<PersonalChannel.Value> getPersonalChannels() {
		return personalChannels;
	}
	protected void setPersonalChannels(
			Collection<PersonalChannel.Value> personalChannels) {
		this.personalChannels = personalChannels;
	}
	protected void setOrganization(Organization.Value organization) {
		this.organization = organization;
	}
	protected void setLeaves(Collection<Leave.Value> leaves) {
		this.leaves = leaves;
	}
	protected void setIntervals(Collection<CprInterval.Value> cprIntervals) {
		this.cprIntervals = cprIntervals;
	}
	public static long getSerialversionuid() {
		return serialVersionUID;
	}
	public Organization.Value getOrganization() {
		return organization;
	}
	public Collection<Leave.Value> getLeaves() {
		return leaves;
	}
	public Collection<CprInterval.Value> getCprIntervals() {
		return cprIntervals;
	}
	public WrappedBitemporalProperty<Value, Bitemporal> getValues() {
    	return new WrappedBitemporalProperty<Value, Bitemporal>(values, new WrappedValueAccessor<Value,Bitemporal>() {
			private static final long serialVersionUID = 1L;

			@Override
			public Bitemporal wrapValue(Value value, Interval validityInterval) {
				Bitemporal bi = new Bitemporal(value, validityInterval);
				return bi;
			}
    	});
    }
}
